package utils

import (
	"sort"
	"strings"
	"sync"
)

/**
 * 可以单独使用
 */
type GSyncMapGroup struct {
	storeMap sync.Map
}

func (this *GSyncMapGroup) Set(id interface{}, val interface{}) {
	this.storeMap.Store(id, val)
}

func (this *GSyncMapGroup) Store(id interface{}, val interface{}) {
	this.storeMap.Store(id, val)
}

func (this *GSyncMapGroup) Contain(id interface{}) bool {
	_, loaded := this.storeMap.Load(id)
	return loaded
}

func (this *GSyncMapGroup) Count() int {
	return SyncMapLength(&this.storeMap)
}

func (this *GSyncMapGroup) CountFunc(fn func(k, v interface{}) bool) int {
	rval := 0
	this.storeMap.Range(func(key, value interface{}) bool {
		if fn(key, value) {
			rval++
		}
		return true
	})
	return rval
}

func (this *GSyncMapGroup) Clear() {
	//this.storeMap = emptyMap    // 测试时发现 存在并发问题
	this.Range(func(key, value interface{}) bool {
		this.Remove(key)
		return true
	})
}

func (this *GSyncMapGroup) Get(id interface{}, def interface{}) interface{} {
	if val, loaded := this.storeMap.Load(id); loaded {
		return val
	} else {
		return def
	}
}

func (this *GSyncMapGroup) LoadOrStoreFunc2(id interface{}, newfunc func() interface{},
	freefunc func(val interface{})) (actual interface{}, loaded bool) {
	if val, loaded := this.storeMap.Load(id); loaded {
		return val, true
	} else {
		newval := newfunc()
		val, loaded := this.storeMap.LoadOrStore(id, newval)
		if loaded && freefunc != nil {
			freefunc(newval)
		}
		return val, loaded
	}
}

func (this *GSyncMapGroup) LoadOrStoreFunc(id interface{}, newfunc func() interface{},
	freefunc func(val interface{})) (actual interface{}) {
	val, _ := this.LoadOrStoreFunc2(id, newfunc, freefunc)
	return val
}

func (this *GSyncMapGroup) LoadOrStore(id interface{}, store interface{}) (actual interface{}, loaded bool) {
	return this.storeMap.LoadOrStore(id, store)
}

func (this *GSyncMapGroup) Remove(id interface{}) {
	this.storeMap.Delete(id)
}

func (this *GSyncMapGroup) RemoveEx(id interface{}) bool {
	_, loaded := this.storeMap.LoadAndDelete(id)
	return loaded
}

func (this *GSyncMapGroup) RemoveAndGet(id interface{}) (val interface{}, ok bool) {
	return this.storeMap.LoadAndDelete(id)
}

func (this *GSyncMapGroup) AsInt32(id interface{}, def int32) int32 {
	if val, loaded := this.storeMap.Load(id); loaded {
		return GetInt32Value(val, def)
	} else {
		return def
	}
}

func (this *GSyncMapGroup) AsString(id interface{}, def string) string {
	if val, loaded := this.storeMap.Load(id); loaded {
		return GetStrValue(val, def)
	} else {
		return def
	}
}

func (this *GSyncMapGroup) Range(f func(key, value interface{}) bool) {
	this.storeMap.Range(f)
}

func (this *GSyncMapGroup) List() []interface{} {
	rval := make([]interface{}, 0, this.Count())
	this.storeMap.Range(func(key, value interface{}) bool {
		rval = append(rval, value)
		return true
	})
	return rval
}

func (this *GSyncMapGroup) ListSorted(lessfunc func(iItm, jItm interface{}) bool) []interface{} {
	rval := make([]interface{}, 0, this.Count())
	this.storeMap.Range(func(key, value interface{}) bool {
		rval = append(rval, value)
		return true
	})

	sort.Slice(rval, func(i, j int) bool {
		return lessfunc(rval[i], rval[j])
	})
	return rval
}

func (this *GSyncMapGroup) PickFirst(filter func(key, value interface{}) bool, less_sortfunc func(iItm, jItm interface{}) bool) interface{} {
	lst := this.ListEx(filter, less_sortfunc)
	if len(lst) > 0 {
		return lst[0]
	} else {
		return nil
	}
}

func (this *GSyncMapGroup) ListEx(filter func(key, value interface{}) bool, less_sortfunc func(iItm, jItm interface{}) bool) []interface{} {
	rval := make([]interface{}, 0, this.Count())
	this.storeMap.Range(func(key, value interface{}) bool {
		if filter != nil {
			if filter(key, value) {
				rval = append(rval, value)
			}
		} else {
			rval = append(rval, value)
		}

		return true
	})

	if less_sortfunc != nil {
		sort.Slice(rval, func(i, j int) bool {
			return less_sortfunc(rval[i], rval[j])
		})
	}

	return rval
}

func (this *GSyncMapGroup) ListRangeV2(filter func(key, value interface{}) bool,
	less_sortfunc func(k0, v0, k1, v1 interface{}) bool,
	rangfn func(key, val interface{}) bool) {
	rval := make([][2]interface{}, 0, this.Count())
	var appendfn = func(key, value interface{}) {
		var itm [2]interface{}
		itm[0] = key
		itm[1] = value
		rval = append(rval, itm)
	}
	this.storeMap.Range(func(key, value interface{}) bool {
		if filter != nil {
			if filter(key, value) {
				appendfn(key, value)
			}
		} else {
			appendfn(key, value)
		}

		return true
	})

	if less_sortfunc != nil {
		sort.Slice(rval, func(i, j int) bool {
			return less_sortfunc(rval[i][0], rval[i][1], rval[j][0], rval[j][1])
		})
	}

	for i := 0; i < len(rval); i++ {
		if !rangfn(rval[i][0], rval[i][1]) {
			return
		}
	}
}

func (this *GSyncMapGroup) ListRangeV3(filterflag, sortflag int, filter func(key, value interface{}) bool,
	less_sortfunc func(k0, v0, k1, v1 interface{}) bool,
	rangfn func(key, val interface{}) bool) {

	if filterflag == 0 && sortflag == 0 {
		this.storeMap.Range(rangfn)
		return
	}

	if sortflag == 0 && filterflag == 1 {
		this.storeMap.Range(func(key, value interface{}) bool {
			if filter != nil {
				if filter(key, value) {
					rangfn(key, value)
				}
			} else {
				rangfn(key, value)
			}

			return true
		})
		return
	}

	rval := make([][2]interface{}, 0, this.Count())
	var appendfn = func(key, value interface{}) {
		var itm [2]interface{}
		itm[0] = key
		itm[1] = value
		rval = append(rval, itm)
	}
	this.storeMap.Range(func(key, value interface{}) bool {
		if filter != nil {
			if filter(key, value) {
				appendfn(key, value)
			}
		} else {
			appendfn(key, value)
		}

		return true
	})

	if less_sortfunc != nil {
		sort.Slice(rval, func(i, j int) bool {
			return less_sortfunc(rval[i][0], rval[i][1], rval[j][0], rval[j][1])
		})
	}

	for i := 0; i < len(rval); i++ {
		if !rangfn(rval[i][0], rval[i][1]) {
			return
		}
	}
}

/*
*

	支持ISearchVal,
	使用ICompareLess进行排序
*/
func (this *GSyncMapGroup) FilterAndSort(searchval interface{}) []interface{} {
	rval := make([]interface{}, 0, this.Count())
	this.storeMap.Range(func(key, value interface{}) bool {
		if searchval == nil {
			rval = append(rval, value)
		} else {
			if TrySearchVal(value, searchval, true) {
				rval = append(rval, value)
			}
		}

		return true
	})

	sort.Slice(rval, func(i, j int) bool {
		return CompareLess(rval[i], rval[j])
	})

	return rval
}

/*
*

	支持ISearchVal,
	使用ICompareLess进行排序
*/
func (this *GSyncMapGroup) FilterAndSortRange(searchval interface{}, fn func(idx int, val interface{}) bool) {
	rval := make([]interface{}, 0, this.Count())
	this.storeMap.Range(func(key, value interface{}) bool {
		if searchval == nil {
			rval = append(rval, value)
		} else {
			if TrySearchVal(value, searchval, true) {
				rval = append(rval, value)
			}
		}

		return true
	})

	sort.Slice(rval, func(i, j int) bool {
		return CompareLess(rval[i], rval[j])
	})

	for i := 0; i < len(rval); i++ {
		if !fn(i, rval[i]) {
			break
		}
	}

	return
}

func (this *GSyncMapGroup) ValAsString(spliter string, filter func(key, value interface{}) bool, less_sortfunc func(iItm, jItm interface{}) bool) string {
	n := 0
	strs := this.ListEx(filter, less_sortfunc)
	if len(strs) > 0 {
		var sb BytesBuilder
		for i := 0; i < len(strs); i++ {
			if v1, ok := strs[i].(string); ok {
				if n > 0 {
					sb.AppendStr(spliter)
				}
				sb.AppendStr(v1)
				n++
			}
		}
		return sb.String()
	}
	return ""
}

/*
**

	ordertype 0:顺序, 1:倒序
*/
func (this *GSyncMapGroup) ValAsString2(spliter string, filter func(key, value interface{}) bool, ordertype int) string {
	return this.ValAsString(spliter, filter, func(iItm, jItm interface{}) bool {
		if ordertype == 0 {
			return iItm.(string) < jItm.(string)
		} else {
			return iItm.(string) > jItm.(string)
		}
	})
}

/*
*

	k=v;k=v;
*/
func (this *GSyncMapGroup) BatchSetFromStr(str string) {
	strs := strings.Split(str, ";")
	for i := 0; i < len(strs); i++ {
		k, v := Split2Str(strs[i], "=")
		this.Set(k, v)
	}
	return
}
